package com.unknown.chainevent.biz.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.unknown.chainevent.biz.event.InitLogFilter;
import com.unknown.chainevent.biz.service.ChainConfigService;
import com.unknown.chainevent.common.constants.ChainEventConstants;
import com.unknown.chainevent.common.entity.ChainConfig;
import com.unknown.chainevent.common.mapper.ChainConfigMapper;
import org.cloud.exception.BusinessException;
import org.cloud.vo.CommonApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;

import java.io.IOException;
import java.math.BigInteger;
import java.util.List;

@Service
public class ChainConfigServiceImpl extends ServiceImpl<ChainConfigMapper, ChainConfig> implements ChainConfigService{

    @Autowired
    private InitLogFilter initLogFilter;
    @Override
    public int insertSelective(ChainConfig record) {
        return baseMapper.insertSelective(record);
    }
    @Override
    public int updateByPrimaryKeySelective(ChainConfig record) {
        return baseMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public int updateLastBlock(Long id, Long block) {
        return getBaseMapper().updateLastBlock(id, block);
    }

    @Override
    public List<ChainConfig> getChainList(boolean onlyValid) {
        return list(
                Wrappers.lambdaQuery(ChainConfig.class)
                        .eq(onlyValid, ChainConfig::getChainStatus, ChainEventConstants.ChainStatusConstants.NORMAL.getStatus())
        );
    }

    @Override
    public CommonApiResult<?> updateChain(ChainConfig config) throws BusinessException, IOException {
        ChainConfig chainConfig = baseMapper.selectById(config.getChainConfigId());
        if (ObjectUtils.isEmpty(chainConfig)) {
            throw new BusinessException("链配置不存在");
        }

        if (!ObjectUtils.isEmpty(config.getRpcAddress()) && !config.getRpcAddress().equals(chainConfig.getRpcAddress())) {
            config.setRpcAddress(config.getRpcAddress().trim());
            Web3j web3j = Web3j.build(new HttpService(config.getRpcAddress()));
            BigInteger chainId = web3j.ethChainId().send().getChainId();
            if (chainId == null){
                return CommonApiResult.createFailResult("无效的RPC地址，获取chainId失败");
            }
            if (chainId.longValue() != chainConfig.getChainId()){
                return CommonApiResult.createFailResult("不能修改不同链的RPC地址");
            }
        }
        ChainConfig updateChainConfig = ChainConfig.builder()
                .chainConfigId(chainConfig.getChainConfigId())
                .rpcAddress(config.getRpcAddress())
                .chainSymbol(chainConfig.getChainSymbol())
                .blockNumber(config.getBlockNumber())
                .chainStatus(config.getChainStatus())
                .confirmBlock(config.getConfirmBlock())
                .distrustBlock(config.getDistrustBlock())
                .scanOldBlock(config.getScanOldBlock())
                .build();
//        LoginUserDetails loginUser = FeignUtil.single().getLoginUser();
//        config.setUpdateBy(loginUser.getUsername());
        int insert = baseMapper.updateByPrimaryKeySelective(updateChainConfig);
        if (insert == 0) {
            throw new BusinessException("修改失败");
        }
        //删除该链的事件扫描器（等待重新初始化）
        initLogFilter.clearLogFilter(chainConfig.getChainConfigId());
        return CommonApiResult.createSuccessResult();
    }

    @Override
    public CommonApiResult<?> addChain(ChainConfig config) throws BusinessException, IOException {
        if (ObjectUtils.isEmpty(config.getRpcAddress())) {
            throw new BusinessException("RPC地址为空");
        }
        config.setRpcAddress(config.getRpcAddress().trim());
        if (ObjectUtils.isEmpty(config.getChainSymbol())) {
            throw new BusinessException("链符号为空");
        }
        if (config.getChainStatus() == null) {
            throw new BusinessException("状态不能为空");
        }
        if (config.getConfirmBlock() == null || config.getConfirmBlock() < 0){
            return CommonApiResult.createFailResult("确认区块数不能为空");
        }
        if (config.getDistrustBlock() == null || config.getDistrustBlock() < 0){
            return CommonApiResult.createFailResult("不信任区块数不能为空");
        }
        if (config.getScanOldBlock() == null || config.getScanOldBlock() < 0){
            return CommonApiResult.createFailResult("旧区块数不能为空");
        }
        Web3j web3j = Web3j.build(new HttpService(config.getRpcAddress()));
        BigInteger chainId = web3j.ethChainId().send().getChainId();
        if (chainId == null){
            return CommonApiResult.createFailResult("获取chainId失败");
        }
        config.setChainId(chainId.longValue());
//        LoginUserDetails loginUser = FeignUtil.single().getLoginUser();
//        config.setCreateBy(loginUser.getUsername());
        int insert = baseMapper.insertSelective(config);
        if (insert == 0) {
            throw new BusinessException("修改失败");
        }
        return CommonApiResult.createSuccessResult();
    }

    @Override
    public CommonApiResult<?> updateStatus(Long chainConfigId, Integer status) throws BusinessException {
        ChainConfig chainConfig = getBaseMapper().selectById(chainConfigId);
        if (ObjectUtils.isEmpty(chainConfig)) {
            throw new BusinessException("链配置不存在");
        }
        ChainConfig config = new ChainConfig();
        config.setChainConfigId(chainConfigId);
        config.setChainStatus(status);
        int update = baseMapper.updateByPrimaryKeySelective(config);
        if (update == 0) {
            throw new BusinessException("更新失败");
        }
        initLogFilter.clearLogFilter(chainConfigId);
        return CommonApiResult.createSuccessResult();
    }
}
